﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using NPOI.OpenXmlFormats.Shared;
using Org.BouncyCastle.Bcpg;
using Word=DocumentFormat.OpenXml.Wordprocessing;

namespace Office.Automatic.Core.Jobs
{
    internal class TempJob20230713 : Job
    {
#pragma warning disable CS8618
        [SuppressMessage("ReSharper", "InconsistentNaming")]
        [SuppressMessage("ReSharper", "IdentifierTypo")]
        class Entry
        {
            public string XM姓名 { get; set; }
            public string XB性别 { get; set; }
            public string CSNY出生年月 { get; set; }
            public string ZZMM政治面貌 { get; set; }
            public string JRDPSJ加入党派时间 { get; set; }
            public string MZ民族 { get; set; }
            public string JG籍贯 { get; set; }
            public string CJGZSJ参加工作时间 { get; set; }
            public string RXZ任现职级层次时间 { get; set; }
            public string XL学历 { get; set; }
            public string XR现任职务 { get; set; }
            public string CPKHQK民主测评及考核情况 { get; set; }
            public string JL简历 { get; set; }

#pragma warning restore CS8618
        }

        public override string Name => "Temp job 20230713";
        public override bool IsTemporary => true;

        private readonly Dictionary<string, Entry> _targets = new Dictionary<string, Entry>();
        public override void Process()
        {
            //LoadData();
            //CheckDataStep01();
            //CheckDataStep02();
            //CreateTable01();
            CreateDocument01();
            Console.WriteLine("Over.");
            Console.ReadKey(false);
        }

        private void ReadTargetData(string path, out Entry? entry)
        {
            using var document =
                WordprocessingDocument.Open(path, false);

            entry = null;

            var mainDocumentPart = document.MainDocumentPart;
            if (mainDocumentPart == null) return;
            var docBody = mainDocumentPart.Document.Body;
            if (docBody == null) return;

            entry =  new Entry()
            {
                XM姓名 = GetTableCellText(docBody, 0, 0, 1),
                XB性别 = GetTableCellText(docBody, 0, 0, 3),
                CSNY出生年月 = GetTableCellText(docBody, 0, 0, 5),
                ZZMM政治面貌 = GetTableCellText(docBody, 0, 1, 1),
                MZ民族 = GetTableCellText(docBody, 0, 1, 3),
                JG籍贯 = GetTableCellText(docBody, 0, 1, 5),
                CJGZSJ参加工作时间 = GetTableCellText(docBody, 0, 2, 1),
                RXZ任现职级层次时间 = GetTableCellText(docBody, 0, 2, 3),
                XL学历 = GetTableCellText(docBody, 0, 2, 5),
                XR现任职务 = GetTableCellText(docBody, 0, 3, 1),
                CPKHQK民主测评及考核情况 = GetTableCellText(docBody, 1, 1, 1)
            };

        }

        private void LoadData()
        {
            _targets.Clear();

            foreach (var file in Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\考核表","*.docx",SearchOption.TopDirectoryOnly))
            {
                ReadTargetData(file, out var entry);
                if (entry != null)
                {
                    _targets.Add(entry.XM姓名, entry);
                }
            }
        }
        /// <summary>
        /// Load 任免表 Data
        /// </summary>
        /// <param name="file"></param>
        /// <param name="entry"></param>
        private void LoadRmbData(string file, out Entry? entry)
        {
            using var document =
                WordprocessingDocument.Open(file, false);

            entry = null;

            var mainDocumentPart = document.MainDocumentPart;
            if (mainDocumentPart == null) return;
            var docBody = mainDocumentPart.Document.Body;
            if (docBody == null) return;

            var tFunc = new Func<Word.TableCell, string?>((cell) =>
            {
                var p = cell.Elements<Word.Paragraph>().FirstOrDefault();
                if (p == null) return null;
                var s = new StringBuilder();
                
                foreach (var e in p.ChildElements)
                {
                    if (e.Elements<Word.Break>().FirstOrDefault() != null) break;
                    if (e is not Word.Run run) continue;
                    s.Append(run.InnerText);
                }

                return s.ToString();
            });

            entry = new Entry()
            {
                XM姓名 = GetTableCellText(docBody, 0, 1, 1),
                XB性别 = GetTableCellText(docBody, 0, 1, 3),
                CSNY出生年月 = GetTableCellText(docBody, 0, 1, 5).Substring(0, 7),
                ZZMM政治面貌 = string.IsNullOrWhiteSpace(GetTableCellText(docBody, 0, 3, 1)) ? "群众" : "中共党员",
                JRDPSJ加入党派时间 = GetTableCellText(docBody, 0, 3, 1),
                MZ民族 = GetTableCellText(docBody, 0, 2, 1),
                JG籍贯 = GetTableCellText(docBody, 0, 2, 3),
                CJGZSJ参加工作时间 = GetTableCellText(docBody, 0, 3, 3),
                RXZ任现职级层次时间 = string.Empty,
                XL学历 = string.IsNullOrWhiteSpace(GetTableCellText(docBody, 0, 6, 2))
                    ? GetTableCellText(docBody, 0, 5, 2, tFunc)
                    : GetTableCellText(docBody, 0, 6, 2, tFunc),
                XR现任职务 = GetTableCellText(docBody, 0, 7, 1),
                CPKHQK民主测评及考核情况 = string.Empty,
                JL简历 = GetTableCellText(docBody, 0, 10, 1, (cell) =>
                {
                    var p = cell.Elements<Word.Paragraph>().FirstOrDefault();
                    if (p == null) return null;
                    var s = new StringBuilder();

                    foreach (var e in p.ChildElements)
                    {
                        if (e is not Word.Run run) continue;
                        foreach (var e2 in e.ChildElements)
                        {
                            if (e2 is Word.Break) s.AppendLine();
                            if (e2 is Word.Text) s.Append(e2.InnerText);
                        }
                    }

                    s.Replace("\r\n                  ", "");
                    return s.ToString();
                })
            };
        }

        [SuppressMessage("ReSharper", "UseStringInterpolation")]
        private void CheckDataStep01()
        {

            var sourceFiles = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\晋升人员任免表", "*.docx");
     
            foreach (var (key, value) in _targets)
            {
                var sourceFile = sourceFiles.FirstOrDefault(t => t.Contains(key));
                if(sourceFile ==null) continue;

                LoadRmbData(sourceFile, out var srcEntry);

                Console.ForegroundColor = ConsoleColor.DarkGray;

                if (srcEntry == null)
                {
                    Console.WriteLine("Member {0} not checked.", value.XM姓名);
                    continue;
                }

                Console.WriteLine("Check {0}...",value.XM姓名);
                var isBroken = false;

                var log = new StringBuilder();

                if (value.XM姓名 != srcEntry.XM姓名)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("姓名: {0} <---> {1}", value.XM姓名, srcEntry.XM姓名));
                }

                if (value.CJGZSJ参加工作时间 != srcEntry.CJGZSJ参加工作时间)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("参加工作时间: {0} <---> {1}", value.CJGZSJ参加工作时间, srcEntry.CJGZSJ参加工作时间));
                }

                if (value.CSNY出生年月 != srcEntry.CSNY出生年月)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("CSNY出生年月: {0} <---> {1}", value.CSNY出生年月, srcEntry.CSNY出生年月));
                }

                if (value.JG籍贯 != srcEntry.JG籍贯)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("JG籍贯: {0} <---> {1}", value.JG籍贯, srcEntry.JG籍贯));
                }

                if (value.MZ民族 != srcEntry.MZ民族)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("MZ民族: {0} <---> {1}", value.MZ民族, srcEntry.MZ民族));
                }

                if (value.XB性别 != srcEntry.XB性别)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("XB性别: {0} <---> {1}", value.XB性别, srcEntry.XB性别));
                }

                if (value.XL学历 != srcEntry.XL学历)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("XL学历: {0} <---> {1}", value.XL学历, srcEntry.XL学历));
                }

                if (value.XR现任职务 != srcEntry.XR现任职务)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("XR现任职务: {0} <---> {1}", value.XR现任职务, srcEntry.XR现任职务));
                }

                if (value.ZZMM政治面貌 != srcEntry.ZZMM政治面貌)
                {
                    isBroken = true;
                    log.AppendLine(string.Format("ZZMM政治面貌: {0} <---> {1}", value.ZZMM政治面貌, srcEntry.ZZMM政治面貌));
                }

                if (value.RXZ任现职级层次时间 != "2019.06")
                {
                    isBroken = true;
                    log.AppendLine(string.Format("RXZ任现职级层次时间: {0} <---> 2019.06", value.RXZ任现职级层次时间));
                }

                if (isBroken)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Error");
                    Console.WriteLine(log.ToString());
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    Console.WriteLine("========");
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Ok");
                }

            }

            //Console.ReadKey(false);
        }

        private void CheckDataStep02()
        {
            var minorWorkbookFiles = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\民主测评票", "*.xlsx");

            using var mainWorkbook = new XLWorkbook(@"C:\Users\loyse\Desktop\20230713\会议推荐汇总表.xlsx");
            
            var mainNameRowIndex = new Dictionary<string, int>();
            for (var i = 5; i <= 154; i++)
            {
                var name= mainWorkbook.Worksheet("适用于县级局").Cell(i, 1).Value.GetText();
                if (string.IsNullOrWhiteSpace(name)) continue;
                mainNameRowIndex.Add(name, i);
            }

            foreach (var (key, value) in _targets)
            {
                var regex1 =
                    new Regex(
                        "会议推荐：应参加推荐会议56人，实到54人，占96.43%，发出推荐票54张，收回54张，其中有效票54张，无效票0张，同意推荐([0-9]{1,})票，推荐率([0-9.]{1,}%)");
                var regex2 =
                    new Regex(
                        "民主测评情况：应参加测评50人，发出测评票50张，收回50张，其中有效票50[ ]{0,1}张，无效票0张，同意晋升([0-9]{1,})票，同意率([0-9.]{1,}%)。民主评价中，综合评价优秀([0-9.]{1,}%)，良好([0-9.]{1,}%)，一般([0-9.]{1,}%)，较差([0-9.]{1,}%)");
                              //民主测评情况：应参加测评50人，发出测评票50张，收回50张，其中有效票50 张，无效票0张，同意晋升50票，同意率100%。民主评价中，综合评价优秀100%，良好0%，一般0%，较差0%。
                var match = regex1.Match(value.CPKHQK民主测评及考核情况);

                bool isMismatch = false;

                if (!match.Success)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Member {0} data01 format incorrect.", value.XM姓名);
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    isMismatch = true;
                }
                else
                {
                    var voteCount = mainWorkbook.Worksheet("适用于县级局").Cell(mainNameRowIndex[value.XM姓名], 16).Value
                        .GetNumber().ToString(CultureInfo.InvariantCulture);
                    var voteRate = mainWorkbook.Worksheet("适用于县级局").Cell(mainNameRowIndex[value.XM姓名], 17).Value.GetText();


                    if (voteCount != match.Groups[1].Value || voteRate != match.Groups[2].Value)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("Member {0} data01 mismatch. Value: {1} -- {2}", value.XM姓名, voteCount, voteRate);
                        Console.ForegroundColor = ConsoleColor.DarkGray;
                        isMismatch = true;
                    }
                }

                var minorWbFile = minorWorkbookFiles.FirstOrDefault(t => t.Contains(value.XM姓名));
                if (minorWbFile != null)
                {
                    using (var workbook = new XLWorkbook(minorWbFile))
                    {
                        var field01 = workbook.Worksheet("适用于县级局").Cell("B7").Value.GetNumber().ToString(CultureInfo.InvariantCulture);
                        var field02 = workbook.Worksheet("适用于县级局").Cell("B8").Value.GetText();
                        var field03= workbook.Worksheet("适用于县级局").Cell("E8").Value.GetText();
                        var field04 = workbook.Worksheet("适用于县级局").Cell("F8").Value.GetText();
                        var field05 = workbook.Worksheet("适用于县级局").Cell("G8").Value.GetText();
                        var field06 = workbook.Worksheet("适用于县级局").Cell("H8").Value.GetText();

                        var match02 = regex2.Match(value.CPKHQK民主测评及考核情况);
                        if (match02.Success)
                        {
                            if (field01 != match02.Groups[1].Value ||
                                field02 != match02.Groups[2].Value ||
                                field03 != match02.Groups[3].Value ||
                                field04 != match02.Groups[4].Value ||
                                field05 != match02.Groups[5].Value ||
                                field06 != match02.Groups[6].Value)
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                Console.WriteLine("Member {0} data02 mismatch. Value: {0}-{1} | {2} | {3} | {4} | {5}",
                                    value.XM姓名, field01, field02, field03, field04, field05, field06);
                                Console.ForegroundColor = ConsoleColor.DarkGray;
                            }
                        }
                        else
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine("Member {0} data02 format incorrect.", value.XM姓名);
                            Console.ForegroundColor = ConsoleColor.DarkGray;
                            isMismatch = true;
                        }
                    }
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Member {0} minor data not found.", value.XM姓名);
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    isMismatch = true;
                }

                Console.ForegroundColor = ConsoleColor.DarkGray;
                if(isMismatch)
                    Console.WriteLine("--------------------");

            }
        }

        private void CreateTable01()
        {
            var members = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\考核表", "*.docx")
                .Select(t =>
                {
                    var name = Path.GetFileName(t);
                    return (name.Substring(0, 2), name.Substring(11, name.IndexOf('）') - 11));
                }).ToArray();


            var rmbFiles = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\晋升人员任免表", "*.docx");

            var wbSubDataFiles = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\民主测评票", "*.xlsx");

            using var wbData = new XLWorkbook(@"C:\Users\loyse\Desktop\20230713\会议推荐汇总表.xlsx");

            var wbDataNameRowIndex = new Dictionary<string, int>();
            for (var i = 5; i <= 154; i++)
            {
                var name = wbData.Worksheet("适用于县级局").Cell(i, 1).Value.GetText();
                if (string.IsNullOrWhiteSpace(name)) continue;
                wbDataNameRowIndex.Add(name, i);
            }

            using var workbook = new XLWorkbook(@"C:\Users\loyse\Desktop\20230713\附件18：工作纪实表（样表）.xlsx");

            foreach (var (memberId, memberName) in members)
            {
                var sheet = workbook.Worksheet("个人部分").CopyTo($"{memberId}.{memberName}");
                var wbDataRow = wbDataNameRowIndex[memberName];

                var rmbFile = rmbFiles.FirstOrDefault(t => t.Contains(memberName));
                if (rmbFile == null)
                {
                    continue;
                }

                LoadRmbData(rmbFile, out var rmbEntry);
                if (rmbEntry == null)
                {
                    continue;
                }

                sheet.Cell("C3").SetValue(rmbEntry.XM姓名);
                sheet.Cell("E3").SetValue(rmbEntry.XB性别);
                sheet.Cell("G3").SetValue(rmbEntry.CSNY出生年月);
                sheet.Cell("I3").SetValue(rmbEntry.JG籍贯);
                sheet.Cell("C4").SetValue(rmbEntry.CJGZSJ参加工作时间);
                sheet.Cell("E4").SetValue(rmbEntry.ZZMM政治面貌);
                sheet.Cell("G4").SetValue(rmbEntry.JRDPSJ加入党派时间);
                if (rmbEntry.XL学历.Length > 4)
                {
                    sheet.Cell("I4").SetValue(rmbEntry.XL学历.Substring(0, 4) + "\r\n" + rmbEntry.XL学历.Substring(4));
                }
                else
                {
                    sheet.Cell("I4").SetValue(rmbEntry.XL学历);
                }

                sheet.Cell("C5").SetValue(rmbEntry.XR现任职务);
                sheet.Cell("E5").SetValue(wbData.Worksheet("适用于县级局").Cell(wbDataRow,10).Value);
                sheet.Cell("G5").SetValue(wbData.Worksheet("适用于县级局").Cell(wbDataRow, 11).Value);
                sheet.Cell("I5").SetValue(wbData.Worksheet("适用于县级局").Cell(wbDataRow, 12).Value);
                sheet.Cell("C6").SetValue(rmbEntry.JL简历);
                sheet.Cell("G9").SetValue(wbData.Worksheet("适用于县级局").Cell(wbDataRow, 16).Value.GetNumber());
                sheet.Cell("H9").SetValue(wbData.Worksheet("适用于县级局").Cell(wbDataRow, 17).Value.GetText());
                sheet.Cell("I9").SetValue(wbData.Worksheet("适用于县级局").Cell(wbDataRow, 18).Value);
                sheet.Cell("C20").SetValue($"　　征求仪征市税务局纪检组意见： 自任现职级以来，未收到涉及{rmbEntry.XM姓名}同志的信访举报或问题线索。");


                var subDataFile = wbSubDataFiles.FirstOrDefault(t => t.Contains(rmbEntry.XM姓名));
                if (subDataFile == null)
                {
                    continue;
                }

                using var wbSubData = new XLWorkbook(subDataFile);

                sheet.Cell("G17").SetValue(wbSubData.Worksheet("适用于县级局").Cell("B7").Value.GetNumber());
                sheet.Cell("H17").SetValue(wbSubData.Worksheet("适用于县级局").Cell("C7").Value.GetNumber());
                sheet.Cell("I17").SetValue(wbSubData.Worksheet("适用于县级局").Cell("D7").Value.GetNumber());
            }

            workbook.SaveAs(@"C:\Users\loyse\Desktop\20230713\附件18：工作纪实表.xlsx");
        }

        private void CreateDocument01()
        {
            var members = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\考核表", "*.docx")
                .Select(t =>
                {
                    var name = Path.GetFileName(t);
                    return (name.Substring(0, 2), name.Substring(11, name.IndexOf('）') - 11));
                }).ToArray();


            var rmbFiles = Directory.GetFiles(@"C:\Users\loyse\Desktop\20230713\晋升人员任免表", "*.docx");


            foreach (var (memberId, memberName) in members)
            {
                var path = $"C:\\Users\\loyse\\Desktop\\20230713\\档案任前审核登记表\\{memberId}-档案任前审核登记表({memberName}).docx";
                File.Copy(@"C:\Users\loyse\Desktop\20230713\干部人事档案任前审核登记表(样表).docx", path, true);
                using var document = WordprocessingDocument.Open(path, true);

                var rmbFile = rmbFiles.FirstOrDefault(t => t.Contains(memberName));
                if (rmbFile == null)
                {
                    continue;
                }

                LoadRmbData(rmbFile, out var rmbEntry);
                if (rmbEntry == null)
                {
                    continue;
                }

                var text = document.MainDocumentPart?.Document?.Body?.Elements<Word.Table>().ElementAt(0)
                    ?.Elements<Word.TableRow>().ElementAt(0)?.Elements<Word.TableCell>().ElementAt(1)
                    .Elements<Word.Paragraph>().ElementAt(0).Elements<Word.Run>().ElementAt(0).Elements<Word.Text>()
                    .First();
                if (text != null)
                    text.Text = rmbEntry.XM姓名; 
                
                text = document.MainDocumentPart?.Document?.Body?.Elements<Word.Table>().ElementAt(0)
                    ?.Elements<Word.TableRow>().ElementAt(0)?.Elements<Word.TableCell>().ElementAt(3)
                    .Elements<Word.Paragraph>().ElementAt(0).Elements<Word.Run>().ElementAt(0).Elements<Word.Text>()
                    .First();
                if (text != null)
                    text.Text = rmbEntry.XR现任职务;

                document.Save();
            }
        }

        private static string GetTableCellText(Word.Body body, int tableIndex, int rowIndex, int colIndex,
            Func<Word.TableCell, string?> parser)
        {
            try
            {
                var table = body.Elements<Word.Table>().ElementAt(tableIndex);
                var cell = table.Elements<Word.TableRow>().ElementAt(rowIndex).Elements<Word.TableCell>()
                    .ElementAt(colIndex);

                var result = parser(cell);
                return result ?? string.Empty;
            }
            catch (ArgumentOutOfRangeException)
            {
                return string.Empty;
            }
            
        }

        private static string GetTableCellText(Word.Body body, int tableIndex, int rowIndex, int colIndex)
        {
            Word.Table table;
            Word.TableCell cell;

            try
            {
                table=body.Elements<Word.Table>().ElementAt(tableIndex);
                cell = table.Elements<Word.TableRow>().ElementAt(rowIndex).Elements<Word.TableCell>()
                    .ElementAt(colIndex);
            }
            catch(ArgumentOutOfRangeException)
            {
                return string.Empty;
            }

            return cell.InnerText;
        }
    }
}
